import CryptoJS from 'crypto-js';
import config from "@/config";
import JSEncrypt from 'jsencrypt'

const tool = {}

/* localStorage */
tool.data = {
    set(key, data, datetime = 0) {
        // 加密
        if (config.LS_ENCRYPTION === "AES") {
            data = tool.crypto.AES.encrypt(JSON.stringify(data), config.LS_ENCRYPTION_key)
        }
        let cacheValue = {
            content: data,
            datetime: parseInt(datetime) === 0 ? 0 : new Date().getTime() + parseInt(datetime) * 1000
        }
        return localStorage.setItem(key, JSON.stringify(cacheValue))
    },
    get(key) {
        try {
            const value = JSON.parse(localStorage.getItem(key))
            if (value) {
                let nowTime = new Date().getTime()
                if (nowTime > value.datetime && value.datetime !== 0) {
                    localStorage.removeItem(key)
                    return null;
                }
                // 解密
                if (config.LS_ENCRYPTION === "AES") {
                    value.content = JSON.parse(tool.crypto.AES.decrypt(value.content, sysConfig.LS_ENCRYPTION_key))
                }
                return value.content
            }
            return null
        } catch (err) {
            return null
        }
    },
    remove(key) {
        return localStorage.removeItem(key)
    },
    clear() {
        return localStorage.clear()
    }
}

/* sessionStorage */
tool.session = {
    set(table, settings) {
        let _set = JSON.stringify(settings)
        return sessionStorage.setItem(table, _set);
    },
    get(table) {
        let data = sessionStorage.getItem(table);
        try {
            data = JSON.parse(data)
        } catch (err) {
            return null
        }
        return data;
    },
    remove(table) {
        return sessionStorage.removeItem(table);
    },
    clear() {
        return sessionStorage.clear();
    }
}

/* cookie */
tool.cookie = {
    set(name, value, config = {}) {
        let cfg = {
            expires: null,
            path: null,
            domain: null,
            secure: false,
            httpOnly: false,
            ...config
        }
        let cookieStr = `${name}=${escape(value)}`
        if (cfg.expires) {
            let exp = new Date()
            exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000)
            cookieStr += `;expires=${exp.toGMTString()}`
        }
        if (cfg.path) {
            cookieStr += `;path=${cfg.path}`
        }
        if (cfg.domain) {
            cookieStr += `;domain=${cfg.domain}`
        }
        document.cookie = cookieStr
    },
    get(name) {
        let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"))
        if (arr != null) {
            return unescape(arr[2])
        } else {
            return null
        }
    },
    remove(name) {
        let exp = new Date()
        exp.setTime(exp.getTime() - 1)
        document.cookie = `${name}=;expires=${exp.toGMTString()}`
    }
}

/* Fullscreen */
tool.screen = function (element) {
    let isFull = !!(document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement);
    if (isFull) {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
    } else {
        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        }
    }
}

/* 复制对象 */
tool.objCopy = function (obj) {
    return JSON.parse(JSON.stringify(obj));
}

/* 日期格式化 */
tool.dateFormat = function (date, fmt = 'yyyy-MM-dd hh:mm:ss') {
    date = new Date(date)
    let o = {
        "M+": date.getMonth() + 1,                 // 月份
        "d+": date.getDate(),                    // 日
        "h+": date.getHours(),                   // 小时
        "m+": date.getMinutes(),                 // 分
        "s+": date.getSeconds(),                 // 秒
        "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
        "S": date.getMilliseconds()             // 毫秒
    };
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    }
    for (let k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        }
    }
    return fmt;
}

/* 千分符 */
tool.groupSeparator = function (num) {
    num = num + '';
    if (!num.includes('.')) {
        num += '.'
    }
    return num.replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
        return $1 + ',';
    }).replace(/\.$/, '');
}

/* 常用加解密 */
tool.crypto = {
    rsaEncrypt(data) {
        let publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArDLzlSlUt+QBOkR+uRChwlFJnQbiJNLQOoo/hRj7xrOKolFP+8xCZoNmYwxkp3NzFHCHBH5ZYtUSowZfTEn1JC/F1wBFkkusi3pBs17RFwkPpDlHSr1I8Nx16BCZESRBhFwW06sRJVMHaARp4XtKh9HAW9rWgun+cY9c9w0nzPNb72ZqXWJHunJ7jPBCmvF86KYkG2ZNPYhJ/fMLbibXxSF2cUe+gtG9Ke/Nn7eJwnW/lMUcq4QNyQHqfSz7iabIQYRp+d/D5N+grsAW41puXyqCKkAc5WUi4wj/EmSzjyuVGk+YOaYSlmr2jI+IZpxqrw2jET7/6H0w15ykGi+YtQIDAQAB'
        // 新建JSEncrypt对象
        let encryptor = new JSEncrypt()
        // 设置公钥
        encryptor.setPublicKey(publicKey)
        // 加密数据
        return encryptor.encrypt(data)
    },
    rsaDecrypt(data) {
        let publicKey = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCsMvOVKVS35AE6RH65EKHCUUmdBuIk0tA6ij+FGPvGs4qiUU/7zEJmg2ZjDGSnc3MUcIcEflli1RKjBl9MSfUkL8XXAEWSS6yLekGzXtEXCQ+kOUdKvUjw3HXoEJkRJEGEXBbTqxElUwdoBGnhe0qH0cBb2taC6f5xj1z3DSfM81vvZmpdYke6cnuM8EKa8XzopiQbZk09iEn98wtuJtfFIXZxR76C0b0p782ft4nCdb+UxRyrhA3JAep9LPuJpshBhGn538Pk36CuwBbjWm5fKoIqQBzlZSLjCP8SZLOPK5UaT5g5phKWavaMj4hmnGqvDaMRPv/ofTDXnKQaL5i1AgMBAAECggEALiKWhTumEYCaXZiVVRLiK9Qog1QhSZlbpZt9ijTX2/Qla/iaE821ao7A4z+iRgTV6798RRVu8F5C2H+wD5nu/kt4V3KgsSHqMBJIwPxhy6inUqnv8lPFU5bVViAASonqrcIYcYxvEw9sOA+aqIkmPj5Rqap3d2qmu5kb4KrbI3sNEWEufOuhR5gMSChQEQsbtl35Y2ae7TprYc9Wb7n6OW72rYqUhabf50rp1xjJO0zoOArxfQXF4JwEJ9OkLjNV+eQKYhcN4nLJBAVrKW23G2NmS765LcmG5jRCURpCQcju7mBMxJBp+EanZhsl0JsutIa0l82JWK3Yf0HKlFRO7wKBgQDASjf+FFdJpTxVvV3PnztePM0aHGcqZZxno8tuH34ciTSppk3FDSynZl9DnYSaICUyfova0HX8fKxuYv3TaHcqFN6onI7MEX1AT9sxKfM3gWA6AQr1J7kljWR+5A6TE1gdkHQWNE0fAQU4N3NG1JFdWUzFi/5o9OzZEfoyPbpCwwKBgQDlQKZWNcCJpSGt7rS3PadH9jPF3cicK/Y6GtavfqKjQkO1b5f16cvuovHk3Nf13ZvbDZ6DhDayG7Ca2J1HM5mgEQS5cD/FgrvEE+Oec/Q1RLOqdqBTTiesxTKnXccyDx20TYA4sY/SfA5OQOUO2628kwEq/YbZAm62P3HhuSIPJwKBgAShRNvfTYK+ccd2uc2H/fv05tNcH7fLnop4TSunone5bgUvteuqt4qIUn7kSg8T+xFOLrvkDRM5RUWbKJVwjH385qeUrXOIcEWeJp72bZ7GhLSg1cy1WiXnU6Yig59S9eowUjs+oyS994w0+ZeZAq8GuWyARG3uh81qO2X+Sn/VAoGBAKIqrD85gLwdYoid3Zntc+J0p0TlUN4gPun1SD4WD0f7PNggW1cqDgb9nqztB5s1KuW2aZXQtbwh2DiA2CiguKBAyZ2/aGz3wIjAJPhWP75andkMVvb2xxvw1pcLwDeJ99IuLHBuMjWLabczMpTjEq/dMStO8c+aZ+RlVtJ8WjprAoGAHU0QkKut3SjdgDdD6M0gaiTwfhMAAEVJxAChDGWd2a6IVO9QW+O3R64n/3yNrf6gSR2ipMsQ86SO/eekD1wjscXjRJW8xsFPw9xob/7C3EjGZ3XmZNmiJQnL5GYCyStF+BwEREHeBlPTOnk4/pKm1F+YCEE+0mOHluEF9Gqu1WI='
        // 新建JSEncrypt对象
        let encryptor = new JSEncrypt()
        // 设置公钥
        encryptor.setPublicKey(publicKey)
        // 加密数据
        return encryptor.decrypt(data)
    },
    //MD5加密
    MD5(data) {
        return CryptoJS.MD5(data).toString()
    },
    //BASE64加解密
    BASE64: {
        encrypt(data) {
            return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
        },
        decrypt(cipher) {
            return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
        }
    },
    //AES加解密
    AES: {
        encrypt(data, secretKey, config = {}) {
            if (secretKey.length % 8 !== 0) {
                console.warn("[Jcx-Ui error]: 秘钥长度需为8的倍数，否则解密将会失败。")
            }
            let result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
                iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
                mode: CryptoJS.mode[config.mode || "ECB"],
                padding: CryptoJS.pad[config.padding || "Pkcs7"]
            })
            return result.toString()
        },
        decrypt(cipher, secretKey, config = {}) {
            let result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
                iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
                mode: CryptoJS.mode[config.mode || "ECB"],
                padding: CryptoJS.pad[config.padding || "Pkcs7"]
            })
            return CryptoJS.enc.Utf8.stringify(result);
        }
    }
}

function transitionJsonToString(jsonObj) {
    // 转换后的jsonObj受体对象
    // let _jsonObj: any = null; // ts写法
    let _jsonObj = null;
    // 判断传入的jsonObj对象是不是字符串，如果是字符串需要先转换为对象，再转换为字符串，这样做是为了保证转换后的字符串为双引号
    if (Object.prototype.toString.call(jsonObj) !== '[object String]') {
        try {
            _jsonObj = JSON.stringify(jsonObj);
        } catch (error) {
            // 转换失败错误信息
            // callback(error);
        }
    } else {
        try {
            jsonObj = jsonObj.replace(/(\')/g, '"');
            _jsonObj = JSON.stringify(JSON.parse(jsonObj));
        } catch (error) {
            // 转换失败错误信息
            // callback(error);
        }
    }
    return _jsonObj;
}

tool.formatJson = function (jsonObj) {
    // 正则表达式匹配规则变量
    let reg = null;
    // 转换后的字符串变量
    let formatted = '';
    // 换行缩进位数
    let pad = 0;
    // 一个tab对应空格位数
    let PADDING = '\t';
    // json对象转换为字符串变量
    let jsonString = transitionJsonToString(jsonObj);
    if (!jsonString) {
        return jsonString;
    }
    // 存储需要特殊处理的字符串段
    let _index = [];
    // 存储需要特殊处理的“再数组中的开始位置变量索引
    let _indexStart = null;
    // 存储需要特殊处理的“再数组中的结束位置变量索引
    let _indexEnd = null;
    // 将jsonString字符串内容通过\r\n符分割成数组
    let jsonArray = [];
    // 正则匹配到{,}符号则在两边添加回车换行
    jsonString = jsonString.replace(/([\{\}])/g, '\r\n$1\r\n');
    // 正则匹配到[,]符号则在两边添加回车换行
    jsonString = jsonString.replace(/([\[\]])/g, '\r\n$1\r\n');
    // 正则匹配到,符号则在两边添加回车换行
    jsonString = jsonString.replace(/(\,)/g, '$1\r\n');
    // 正则匹配到要超过一行的换行需要改为一行
    jsonString = jsonString.replace(/(\r\n\r\n)/g, '\r\n');
    // 正则匹配到单独处于一行的,符号时需要去掉换行，将,置于同行
    jsonString = jsonString.replace(/\r\n\,/g, ',');
    // 特殊处理双引号中的内容
    jsonArray = jsonString.split('\r\n');
    jsonArray.forEach(function (node, index) {
        // 获取当前字符串段中"的数量
        let num = node.match(/\"/g) ? node.match(/\"/g).length : 0;
        // 判断num是否为奇数来确定是否需要特殊处理
        if (num % 2 && !_indexStart) {
            _indexStart = index;
        }
        if (num % 2 && _indexStart && _indexStart !== index) {
            _indexEnd = index;
        }
        // 将需要特殊处理的字符串段的其实位置和结束位置信息存入，并对应重置开始时和结束变量
        if (_indexStart && _indexEnd) {
            _index.push({
                start: _indexStart,
                end: _indexEnd,
            });
            _indexStart = null;
            _indexEnd = null;
        }
    });
    // 开始处理双引号中的内容，将多余的"去除
    _index.reverse().forEach(function (item, index) {
        let newArray = jsonArray.slice(item.start, item.end + 1);
        jsonArray.splice(item.start, item.end + 1 - item.start, newArray.join(''));
    });
    // 将处理后的数组通过\r\n连接符重组为字符串
    jsonString = jsonArray.join('\r\n');
    // 将匹配到:后为回车换行加大括号替换为冒号加大括号
    jsonString = jsonString.replace(/\:\r\n\{/g, ':{');
    // 将匹配到:后为回车换行加中括号替换为冒号加中括号
    jsonString = jsonString.replace(/\:\r\n\[/g, ':[');
    // 将上述转换后的字符串再次以\r\n分割成数组
    jsonArray = jsonString.split('\r\n');
    // 将转换完成的字符串根据PADDING值来组合成最终的形态
    jsonArray.forEach(function (item, index) {
        let i = 0;
        // 表示缩进的位数，以tab作为计数单位
        let indent = 0;
        // 表示缩进的位数，以空格作为计数单位
        let padding = '';
        if (item.match(/\{$/) || item.match(/\[$/)) {
            // 匹配到以{和[结尾的时候indent加1
            indent += 1;
        } else if (
            item.match(/\}$/) ||
            item.match(/\]$/) ||
            item.match(/\},$/) ||
            item.match(/\],$/)
        ) {
            // 匹配到以}和]结尾的时候indent减1
            if (pad !== 0) {
                pad -= 1;
            }
        } else {
            indent = 0;
        }
        for (i = 0; i < pad; i++) {
            padding += PADDING;
        }
        formatted += padding + item + '\r\n';
        pad += indent;
    });
    // 返回的数据需要去除两边的空格和换行
    return formatted
        .trim()
        .replace(new RegExp('^\\' + '<br />' + '+|\\' + '<br />' + '+$', 'g'), '');
}

tool.getJti = function () {
    return tool.data.get("APP_TOKEN");
}

export default tool
